library(tidyverse)
Loading tidyverse: ggplot2
Loading tidyverse: tibble
Loading tidyverse: tidyr
Loading tidyverse: readr
Loading tidyverse: purrr
Loading tidyverse: dplyr
package ‘purrr’ was built under R version 3.4.2Conflicts with tidy packages ---------------------------------------------------------------------------------------
filter(): dplyr, stats
lag():    dplyr, stats

PCA

Motivation

Now that we know the two states with the greatest decline in life expectancy are Mississippi and West Virginia, let’s explore what explains the variation among the counties in those states. We know how County Health Rankings approach the 29 health measures, where they group them into four categories and weight them: Health Behaviors (30%), Clinical Care (20%), Social and Economic Factors (40%), and Physical Environment (10%).

We want to see if these group classifications and their weights hold up in explaining the declining life expectancy (and presumably poorer health) in Mississippi and West Virginia. Using PCA, if the 29 measures cluster differently than CHR’s four health factor categories, what kind of story does that tell us? What are shared county characteristics and how might they affect health? How can organizations like CHR take this story into account when computing future rankings, or how can states using information from PCA to address their less healthy residents?

We’ll begin by creating a data frame of ONLY z-scores for the 29 variables, for Misssissippi and West Virginia.

#Create variables-only table for MS and KY
varMS <- zMS_KY%>% filter(State=="Mississippi")
varMS <- varMS[c(5:33)] 
varKY <- zMS_KY%>% filter(State=="Kentucky")
varKY <- varKY[c(5:33)] 

Mississippi

When we try to use prcomp on variables in Mississippi, we get an error since there are missing values.

MS.pca <- prcomp(varMS,
                 center = TRUE,
                 scale. = TRUE) 

Turns out, there are 91 missing values across the 82 counties for MS.

sum(is.na(varMS))
[1] 91

We have 91 missing values across the 82 counties for MS.

varMS.na.omit<- na.omit(varMS)

We could delete rows with missing data, but then we would lose half of our counties. Instead, we can fill in the missing values with 0s, or the mean.

sum(is.na(varMS))
[1] 0

With NAs replaced with 0s, we can try PCA again.

summary(MS.pca)
Importance of components%s:
                          PC1    PC2     PC3     PC4     PC5     PC6     PC7     PC8     PC9   PC10
Standard deviation     2.8111 2.1524 1.34083 1.24265 1.16398 1.11847 1.05761 0.99514 0.97202 0.9435
Proportion of Variance 0.2725 0.1598 0.06199 0.05325 0.04672 0.04314 0.03857 0.03415 0.03258 0.0307
Cumulative Proportion  0.2725 0.4322 0.49423 0.54748 0.59420 0.63734 0.67591 0.71006 0.74264 0.7733
                          PC11    PC12    PC13    PC14    PC15    PC16    PC17    PC18    PC19
Standard deviation     0.89412 0.80913 0.79269 0.76739 0.76124 0.67448 0.66556 0.64456 0.61668
Proportion of Variance 0.02757 0.02258 0.02167 0.02031 0.01998 0.01569 0.01527 0.01433 0.01311
Cumulative Proportion  0.80090 0.82348 0.84514 0.86545 0.88543 0.90112 0.91639 0.93072 0.94383
                          PC20    PC21    PC22    PC23    PC24    PC25    PC26    PC27    PC28
Standard deviation     0.55252 0.51773 0.47882 0.42324 0.40596 0.36806 0.34114 0.31375 0.26678
Proportion of Variance 0.01053 0.00924 0.00791 0.00618 0.00568 0.00467 0.00401 0.00339 0.00245
Cumulative Proportion  0.95436 0.96360 0.97151 0.97769 0.98337 0.98804 0.99205 0.99545 0.99790
                         PC29
Standard deviation     0.2467
Proportion of Variance 0.0021
Cumulative Proportion  1.0000

From our summary of PCA for health factors in Missisippi, we see that the first PC accounts for 27.25% of variance. If we wanted to use four components, like the four fous areas that the CHR currently uses, then we would account for 54.7% of total variance. We would need 8 PCs to get to 71%, 11 to get to 80%, and 16 to get to 90%. At 16 PCs, it would be very difficult to keep track of 16 domains for something like the County Health Rankings, and even at 8 it is still unwieldly. Perhaps we should focus on a smaller number of components, but consider what each component is trying to tell us and also try the ‘rule of 1’ and looking at the ‘elbow’ of a scree plot.

The rule of 1, or retaining eigenvalues of 1 or more, would lead us to choosing seven principal components. Looking at the scree plot below, we would choose four principal components, since it appears that the variance levels off after four components.

Let’s look at the loadings on the first four PCs and interpret what the loadings are trying to describe. The measures were color coded by what CHR categorized these measures into to compare their categorization and PCA’s categorization.

First, we create a data frame of the loadings and combine them with the CHR factor categories.

loadings <- as.data.frame(MS.pca$rotation) #create a data frame of PCA loadings
library(reshape2)
melted <-  melt(MS.pca$rotation[,1:4])
melted <- full_join(melted, factornames, by = c("Var1"= "Measure_Abb")) #join the CHR categories
Column `Var1`/`Measure_Abb` joining factor and character vector, coercing into character vector

PC1

The PC had high positive loadings for children in poverty, children in single parent households, unemployment, adult obesity, STIs, teen births, and inadequate social supports. There was also significant negative loading in the food environment index, indicating higher weights for counties that perform poorly here. PC1 can be interpreted as unstable or poor-resource home environments. It is important to note that loadings with higher measures were categorized as Health Behaviors and Social and Economic Environment had the highest loadings here, suggesting that the two categories may not be so different.

PC2

PC2 sees higher positive weights for dentists, primary care physicians, mental health providers, college education, and violent crime. The greatest magnitude negative weights include long commutes driving alone. This PC can be interpreted as density of services, where there is a higher density of health care providers, opportunities for higher education, and incidentally, violent crime. The negative loading on long commute complements the higher loadings, where shorter driving/commuting distances are associted with urban settings.

PC3

Severe housing problems and being uninsured have high positive loadings for PC3, while driving alone to work and alcohol-impaired driving deaths have high negative violations. CHR’s PHysical Environment categorization is more represented here, followed by one Clinical Care measure (uninsured) and one Health Behavior measure (alcohol-impaired driving deaths). Although this is more difficult to interpret, this PC describes being uninsured against accidents.

PC4

Finally, PC4 sees high loading on air pollution and access to exercise opportunities, again alluding to the urban context but specifically referring to the inability to access the outdoors.

Weights

These four PCs can be assigned weights calculated by the percent of variance each PC accounts for divided by the total amount o variance the chosen PCs account for.

\[ Factor_1 = \frac{0.2725}{0.54748}, Factor_2 = \frac{0.1598}{0.54748}, Factor_3 = \frac{0.06199}{0.54748} ,Factor_4=\frac{0.05325}{0.54748} \]

The four PCs are the following: * 49.8% Resource-poor Home Environments * 29.2% Density of Services * 11.3% Uninsured * 9.7% No Outdoor Access

Interestingly for Mississippi, county scores on what CHR considers health measures actually fall into categories of home environemnts, access to providers, insurance, and outdoor activities. Our Principal Component Analaysis that being ‘healthy’ has a lot less to do with whether counties participate in healthy behaviors, but whether there are opportunities for individuals to grow up in healthy environments and seek affordable healthcare when they need it.

West Virginia

Now we’ll take a look at the same process for West Virginia.

varWV <- varWV %>% mutate_all(funs(ifelse(is.na(.), 0, .)))
WV.pca <- prcomp(varWV,
                 center = TRUE,
                 scale. = TRUE) 
summary(WV.pca)
Importance of components%s:
                          PC1    PC2     PC3     PC4     PC5     PC6     PC7     PC8     PC9    PC10
Standard deviation     2.8283 1.9244 1.58975 1.41104 1.24852 1.19385 1.04259 0.97107 0.95061 0.90246
Proportion of Variance 0.2758 0.1277 0.08715 0.06866 0.05375 0.04915 0.03748 0.03252 0.03116 0.02808
Cumulative Proportion  0.2758 0.4036 0.49070 0.55936 0.61311 0.66226 0.69974 0.73225 0.76341 0.79150
                          PC11    PC12    PC13    PC14    PC15    PC16    PC17    PC18    PC19
Standard deviation     0.87025 0.86111 0.81471 0.72911 0.68445 0.64769 0.60980 0.56411 0.53509
Proportion of Variance 0.02611 0.02557 0.02289 0.01833 0.01615 0.01447 0.01282 0.01097 0.00987
Cumulative Proportion  0.81761 0.84318 0.86607 0.88440 0.90056 0.91502 0.92784 0.93882 0.94869
                          PC20    PC21    PC22   PC23    PC24    PC25   PC26    PC27   PC28    PC29
Standard deviation     0.52732 0.49788 0.48217 0.4028 0.37508 0.37093 0.3448 0.27594 0.2408 0.18967
Proportion of Variance 0.00959 0.00855 0.00802 0.0056 0.00485 0.00474 0.0041 0.00263 0.0020 0.00124
Cumulative Proportion  0.95828 0.96683 0.97484 0.9804 0.98529 0.99003 0.9941 0.99676 0.9988 1.00000
screeplot(WV.pca, npcs = 29, type = "lines")

Based on the scree plot, we can choose four principal components again.

loadings <- as.data.frame(WV.pca$rotation) #create a data frame of PCA loadings
melted <-  melt(WV.pca$rotation[,1:4])
melted <- full_join(melted, factornames, by = c("Var1"= "Measure_Abb")) #join the CHR categories
Column `Var1`/`Measure_Abb` joining factor and character vector, coercing into character vector

PC1

melted %>% filter(Var2=="PC1") %>% 
  ggplot(aes(x = reorder(Measure,-value),y = value, fill=Factors)) + 
  geom_bar(stat="identity") + 
  facet_wrap(~Var2) + 
  xlab("Measures") + 
  ylab("Values") + 
  ggtitle("Loadings for PC1 (WV)") +
  theme(axis.text.x = element_text(angle = 60, hjust = 1))

This time, we have high positive loading on some college education, availability of health care providers (dentistry, mental health, and primary care), and STIs and access to exercise opportunities. There is high negative loading on physical inactivity, adult obesity, injury deaths, and children in poverty. PC1 summarizes the domain of having access to health care providers and knowing how to seek care, as well as being more physically active and financially secure. This PC1 can be summarized as health engagement.

PC2

melted %>% filter(Var2=="PC2") %>% 
  ggplot(aes(x = reorder(Measure,-value),y = value, fill=Factors)) + 
  geom_bar(stat="identity") + 
  facet_wrap(~Var2) + 
  xlab("Measures") + 
  ylab("Values") + 
  ggtitle("Loadings for PC2 (WV)") +
  theme(axis.text.x = element_text(angle = 60, hjust = 1))

In PC2, more measures have high positive loading than high negative loadings. The positive loadings include teen births, health care providers, violent crime, driving alone to work, STIs, inadequate social support, and injury deaths. Negative loadings include high school graduation, long commute/driving alone, and excessive drinking. This component appears less health related, but rather describes young and poor families in small towns. This is similar to the unstable home environment PC for Mississippi.

PC3

melted %>% filter(Var2=="PC3") %>% 
  ggplot(aes(x = reorder(Measure,-value),y = value, fill=Factors)) + 
  geom_bar(stat="identity") + 
  facet_wrap(~Var2) + 
  xlab("Measures") + 
  ylab("Values") + 
  ggtitle("Loadings for PC3 (WV)") +
  theme(axis.text.x = element_text(angle = 60, hjust = 1))

For PC3, there are more negative loadings than positive. Negative loading includes excessive drinking, severe housing problems, drinking water violations, children in poor households, and being uninsured. There is high positive loading for food environment, followed by driving alone to work. This PC describes unhealthy consumption patterns and living in unsafe environments, and can be called toxic consumption.

PC4

melted %>% filter(Var2=="PC4") %>% 
  ggplot(aes(x = reorder(Measure,-value),y = value, fill=Factors)) + 
  geom_bar(stat="identity") + 
  facet_wrap(~Var2) + 
  xlab("Measures") + 
  ylab("Values") + 
  ggtitle("Loadings for PC4 (WV)") +
  theme(axis.text.x = element_text(angle = 60, hjust = 1))

Finally, PC4 describes air pollution (similar to to Missisippi), as well as low diabetic screening and uninsurance rates. This PC is puzzling to interpret, though it should be noted that diabetic screening refers to the percentage of Medicare enrollees (age 65+) who receive HbA1c screening, while the uninsurance rate refers to the percent of the population under age 65 who do not have health insurance. Therefore, this PC might describe counties with younger, insured populations where pollution, and perhaps industry (coal), is present. This relationship was explored further with maps, where areas of low uninsurance arates and high pollution are northern counties bordering Pennsylvania. This PC could be called occupational health.

county_choropleth(WV_uninsure, 
                   title         = "Uninsured Z-Scores in West Virginia", 
                   legend        = "Uninsured  Z-Scores",
                   state_zoom    = "west virginia",
                   reference_map = TRUE)
Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=38.625313,-80.646389&zoom=7&size=640x640&scale=2&maptype=terrain&language=en-EN&sensor=false
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing
scale.
Scale for 'y' is already present. Adding another scale for 'y', which will replace the existing
scale.

county_choropleth(WV_air, 
                   title         = "Air Pollution Z-Scores in West Virginia", 
                   legend        = "Air Pollution Z-Scores",
                   state_zoom    = "west virginia",
                   reference_map = TRUE)
Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=38.625313,-80.646389&zoom=7&size=640x640&scale=2&maptype=terrain&language=en-EN&sensor=false
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing
scale.
Scale for 'y' is already present. Adding another scale for 'y', which will replace the existing
scale.

\[ Factor_1 = \frac{0.2758}{0.55936}, Factor_2 = \frac{0.1277}{0.55936}, Factor_3 = \frac{0.08715}{0.55936} ,Factor_4=\frac{0.06866}{0.55936} \]

The four PCs for West Virginia are the following: * 49.3% Health Engagement * 22.8% Unstable Home Environment * 15.6% Toxic Consumption * 12.2% Occupational Health

CHR vs. PCA

“Historically Informed” Weights vs. Empirical Weights

On the County Health Ranking website, they discuss organizing 29 measures of health into four components and choosing weights based on “scientific research, available data, expert opinion, statistical analysis.” In our Principal Component Analysis, we used a purely empirical approach to analyze the variance across counties in the two states that saw the greatest decline in life expectancy. We wanted to see what matters most to ‘health’ in these states’ counties, and if the weights for the different categories would be different from CHR. However, once we actually performed the analysis on the 29 measures, we realized that the components were describing issues of welfare, the built and physical environment, and access to and engagement with health services. A table comparing the components and weights from CHR and our PCA analyses is shown below:

CHR MS PCA WV PCA
40% Social and Economic Environment 49.8% Resource-poor Home Environments 49.3% Health Engagement
30% Health Behaviors 29.2% Density of Services 22.8% Unstable Home Environment
20% Clinical Care 11.3% Uninsured 15.6% Toxic Consumption
10% Physical Environment 9.7% No Outdoor Access 12.2% Occupational Health

For CHR, a county’s health is determined largely by social and economic environments and health behaviors, which accounts for 70% of their overall health measure. For our PCA analyses, these social and economic determinants appeared in many of the principal components for both states, along with other measures that were considered separate from Social and Economic Factors by CHR– such as density of providers, unsafe drinking water, teen births, and air pollution. Our PCs for Mississippi and West Virginia highlight the social context of these environmental factors, and how they are so interconnected.

For example, our components determined for PCA in Mississippi described the importance of home and physical environments, as well as proximity to health services and being insured against accidents. In West Virginia, the components describe engagement with healthy activities, as well as again, poor home environments or toxic physical environments. These components emphasize the importance of where people live, where location determines the conditions that affect their health (pollution, unsafe housing, exercise opportunities), and how likely it is that they are able to access health services when care is needed (distance to providers and insurance).

Implications for our principal component analyses include focusing on the built and physical environments of communities Improving housing, environmental conditions, and ensuring access (geographically and financially) to health services, are likely to impact communites more than addressing specific health factors like STIs or monitoring diabetes. This contrasts from the implications of CHR’s weights, where physical environment and clinical care are thought to be different from social/economic factors and health behaviors.

What next?

With our PCA analyses, we were able to describe new patterns of health determinants and behaviors that differed from how CHR perceives health. CHR states that their mission in creating these rankings is to provide states with information about where and how to focus their energies in improving population health. We hope that a different approach to these rankings using PCA point to other patterns in population health, and encourage a more holistic, social welfare approach to improving health. PCA tells us that what are traditionally ‘health measures’ actually describe social well being as well, which should be a focus in public health efforts.

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoY2hvcm9wbGV0aHIpCmxpYnJhcnkoY2hvcm9wbGV0aHJNYXBzKQoKYGBgCgoKI1BDQQoKIyNNb3RpdmF0aW9uCk5vdyB0aGF0IHdlIGtub3cgdGhlIHR3byBzdGF0ZXMgd2l0aCB0aGUgZ3JlYXRlc3QgZGVjbGluZSBpbiBsaWZlIGV4cGVjdGFuY3kgYXJlIE1pc3Npc3NpcHBpIGFuZCBXZXN0IFZpcmdpbmlhLCBsZXQncyBleHBsb3JlIHdoYXQgZXhwbGFpbnMgdGhlIHZhcmlhdGlvbiBhbW9uZyB0aGUgY291bnRpZXMgaW4gdGhvc2Ugc3RhdGVzLiBXZSBrbm93IGhvdyBbQ291bnR5IEhlYWx0aCBSYW5raW5nc10oaHR0cDovL3d3dy5jb3VudHloZWFsdGhyYW5raW5ncy5vcmcvb3VyLWFwcHJvYWNoKSBhcHByb2FjaCB0aGUgMjkgaGVhbHRoIG1lYXN1cmVzLCB3aGVyZSB0aGV5IGdyb3VwIHRoZW0gaW50byBmb3VyIGNhdGVnb3JpZXMgYW5kIHdlaWdodCB0aGVtOiBIZWFsdGggQmVoYXZpb3JzICgzMCUpLCBDbGluaWNhbCBDYXJlICgyMCUpLCBTb2NpYWwgYW5kIEVjb25vbWljIEZhY3RvcnMgKDQwJSksIGFuZCBQaHlzaWNhbCBFbnZpcm9ubWVudCAoMTAlKS4gCgpXZSB3YW50IHRvIHNlZSBpZiB0aGVzZSBncm91cCBjbGFzc2lmaWNhdGlvbnMgYW5kIHRoZWlyIHdlaWdodHMgaG9sZCB1cCBpbiBleHBsYWluaW5nIHRoZSBkZWNsaW5pbmcgbGlmZSBleHBlY3RhbmN5IChhbmQgcHJlc3VtYWJseSBwb29yZXIgaGVhbHRoKSBpbiBNaXNzaXNzaXBwaSBhbmQgV2VzdCBWaXJnaW5pYS4gVXNpbmcgUENBLCBpZiB0aGUgMjkgbWVhc3VyZXMgY2x1c3RlciBkaWZmZXJlbnRseSB0aGFuIENIUidzIGZvdXIgaGVhbHRoIGZhY3RvciBjYXRlZ29yaWVzLCB3aGF0IGtpbmQgb2Ygc3RvcnkgZG9lcyB0aGF0IHRlbGwgdXM/IFdoYXQgYXJlIHNoYXJlZCBjb3VudHkgY2hhcmFjdGVyaXN0aWNzIGFuZCBob3cgbWlnaHQgdGhleSBhZmZlY3QgaGVhbHRoPyBIb3cgY2FuIG9yZ2FuaXphdGlvbnMgbGlrZSBDSFIgdGFrZSB0aGlzIHN0b3J5IGludG8gYWNjb3VudCB3aGVuIGNvbXB1dGluZyBmdXR1cmUgcmFua2luZ3MsIG9yIGhvdyBjYW4gc3RhdGVzIHVzaW5nIGluZm9ybWF0aW9uIGZyb20gUENBIHRvIGFkZHJlc3MgdGhlaXIgbGVzcyBoZWFsdGh5IHJlc2lkZW50cz8KCldlJ2xsIGJlZ2luIGJ5IGNyZWF0aW5nIGEgZGF0YSBmcmFtZSBvZiBPTkxZIHotc2NvcmVzIGZvciB0aGUgMjkgdmFyaWFibGVzLCBmb3IgTWlzc3Npc3NpcHBpIGFuZCBXZXN0IFZpcmdpbmlhLiAKCmBgYHtyfQpsb2FkKGZpbGU9ICJaLXNjb3Jlc19NU19XViIpCgp2YXJNUyA8LSB6TVNfV1YlPiUgZmlsdGVyKFN0YXRlPT0iTWlzc2lzc2lwcGkiKQp2YXJNUyA8LSB2YXJNU1tjKDU6MzMpXSAKCnZhcldWIDwtIHpNU19XViU+JSBmaWx0ZXIoU3RhdGU9PSJXZXN0IFZpcmdpbmlhIikKdmFyV1YgPC0gdmFyV1ZbYyg1OjMzKV0gCmBgYAoKIyNNaXNzaXNzaXBwaQoKV2hlbiB3ZSB0cnkgdG8gdXNlIHByY29tcCBvbiB2YXJpYWJsZXMgaW4gTWlzc2lzc2lwcGksIHdlIGdldCBhbiBlcnJvciBzaW5jZSB0aGVyZSBhcmUgbWlzc2luZyB2YWx1ZXMuCmBgYHtyfQpNUy5wY2EgPC0gcHJjb21wKHZhck1TLAogICAgICAgICAgICAgICAgIGNlbnRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgc2NhbGUuID0gVFJVRSkgCmBgYAoKVHVybnMgb3V0LCB0aGVyZSBhcmUgOTEgbWlzc2luZyB2YWx1ZXMgYWNyb3NzIHRoZSA4MiBjb3VudGllcyBmb3IgTVMuIAoKYGBge3J9CnN1bShpcy5uYSh2YXJNUykpCmBgYAoKV2UgaGF2ZSA5MSBtaXNzaW5nIHZhbHVlcyBhY3Jvc3MgdGhlIDgyIGNvdW50aWVzIGZvciBNUy4gCgpgYGB7cn0KdmFyTVMubmEub21pdDwtIG5hLm9taXQodmFyTVMpCmBgYAoKV2UgY291bGQgZGVsZXRlIHJvd3Mgd2l0aCBtaXNzaW5nIGRhdGEsIGJ1dCB0aGVuIHdlIHdvdWxkIGxvc2UgaGFsZiBvZiBvdXIgY291bnRpZXMuIEluc3RlYWQsIHdlIGNhbiBmaWxsIGluIHRoZSBtaXNzaW5nIHZhbHVlcyB3aXRoIDBzLCBvciB0aGUgbWVhbi4gCgpgYGB7cn0KdmFyTVMgPC0gdmFyTVMgJT4lIG11dGF0ZV9hbGwoZnVucyhpZmVsc2UoaXMubmEoLiksIDAsIC4pKSkKYGBgCgpXaXRoIE5BcyByZXBsYWNlZCB3aXRoIDBzLCB3ZSBjYW4gdHJ5IFBDQSBhZ2Fpbi4KCmBgYHtyfQpNUy5wY2EgPC0gcHJjb21wKHZhck1TLAogICAgICAgICAgICAgICAgIGNlbnRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgc2NhbGUuID0gVFJVRSkgCnN1bW1hcnkoTVMucGNhKQpgYGAKCkZyb20gb3VyIHN1bW1hcnkgb2YgUENBIGZvciBoZWFsdGggZmFjdG9ycyBpbiBNaXNzaXNpcHBpLCB3ZSBzZWUgdGhhdCB0aGUgZmlyc3QgUEMgYWNjb3VudHMgZm9yIDI3LjI1JSBvZiB2YXJpYW5jZS4gSWYgd2Ugd2FudGVkIHRvIHVzZSBmb3VyIGNvbXBvbmVudHMsIGxpa2UgdGhlIGZvdXIgZm91cyBhcmVhcyB0aGF0IHRoZSBDSFIgY3VycmVudGx5IHVzZXMsIHRoZW4gd2Ugd291bGQgYWNjb3VudCBmb3IgNTQuNyUgb2YgdG90YWwgdmFyaWFuY2UuIFdlIHdvdWxkIG5lZWQgOCBQQ3MgdG8gZ2V0IHRvIDcxJSwgMTEgdG8gZ2V0IHRvIDgwJSwgYW5kIDE2IHRvIGdldCB0byA5MCUuIEF0IDE2IFBDcywgaXQgd291bGQgYmUgdmVyeSBkaWZmaWN1bHQgdG8ga2VlcCB0cmFjayBvZiAxNiBkb21haW5zIGZvciBzb21ldGhpbmcgbGlrZSB0aGUgQ291bnR5IEhlYWx0aCBSYW5raW5ncywgYW5kIGV2ZW4gYXQgOCBpdCBpcyBzdGlsbCB1bndpZWxkbHkuIFBlcmhhcHMgd2Ugc2hvdWxkIGZvY3VzIG9uIGEgc21hbGxlciBudW1iZXIgb2YgY29tcG9uZW50cywgYnV0IGNvbnNpZGVyIHdoYXQgZWFjaCBjb21wb25lbnQgaXMgdHJ5aW5nIHRvIHRlbGwgdXMgYW5kIGFsc28gdHJ5IHRoZSAncnVsZSBvZiAxJyBhbmQgbG9va2luZyBhdCB0aGUgJ2VsYm93JyBvZiBhIHNjcmVlIHBsb3QuIAoKVGhlIHJ1bGUgb2YgMSwgb3IgcmV0YWluaW5nIGVpZ2VudmFsdWVzIG9mIDEgb3IgbW9yZSwgd291bGQgbGVhZCB1cyB0byBjaG9vc2luZyBzZXZlbiBwcmluY2lwYWwgY29tcG9uZW50cy4gCkxvb2tpbmcgYXQgdGhlIHNjcmVlIHBsb3QgYmVsb3csIHdlIHdvdWxkIGNob29zZSBmb3VyIHByaW5jaXBhbCBjb21wb25lbnRzLCBzaW5jZSBpdCBhcHBlYXJzIHRoYXQgdGhlIHZhcmlhbmNlIGxldmVscyBvZmYgYWZ0ZXIgZm91ciBjb21wb25lbnRzLiAKCmBgYHtyfQpzY3JlZXBsb3QoTVMucGNhLCBucGNzID0gMjksIHR5cGUgPSAibGluZXMiKQpgYGAKCkxldCdzIGxvb2sgYXQgdGhlIGxvYWRpbmdzIG9uIHRoZSBmaXJzdCBmb3VyIFBDcyBhbmQgaW50ZXJwcmV0IHdoYXQgdGhlIGxvYWRpbmdzIGFyZSB0cnlpbmcgdG8gZGVzY3JpYmUuIFRoZSBtZWFzdXJlcyB3ZXJlIGNvbG9yIGNvZGVkIGJ5IHdoYXQgQ0hSIGNhdGVnb3JpemVkIHRoZXNlIG1lYXN1cmVzIGludG8gdG8gY29tcGFyZSB0aGVpciBjYXRlZ29yaXphdGlvbiBhbmQgUENBJ3MgY2F0ZWdvcml6YXRpb24uIAoKRmlyc3QsIHdlIGNyZWF0ZSBhIGRhdGEgZnJhbWUgb2YgdGhlIGxvYWRpbmdzIGFuZCBjb21iaW5lIHRoZW0gd2l0aCB0aGUgQ0hSIGZhY3RvciBjYXRlZ29yaWVzLiAKYGBge3J9CmxvYWRpbmdzIDwtIGFzLmRhdGEuZnJhbWUoTVMucGNhJHJvdGF0aW9uKSAjY3JlYXRlIGEgZGF0YSBmcmFtZSBvZiBQQ0EgbG9hZGluZ3MKCmxpYnJhcnkocmVzaGFwZTIpCgptZWx0ZWQgPC0gIG1lbHQoTVMucGNhJHJvdGF0aW9uWywxOjRdKQoKbWVsdGVkIDwtIGZ1bGxfam9pbihtZWx0ZWQsIGZhY3Rvcm5hbWVzLCBieSA9IGMoIlZhcjEiPSAiTWVhc3VyZV9BYmIiKSkgI2pvaW4gdGhlIENIUiBjYXRlZ29yaWVzCmBgYAoKIyMjUEMxCmBgYHtyfQptZWx0ZWQgJT4lIGZpbHRlcihWYXIyPT0iUEMxIikgJT4lIAogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoTWVhc3VyZSwtdmFsdWUpLHkgPSB2YWx1ZSwgZmlsbD1GYWN0b3JzKSkgKyAKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsgCiAgZmFjZXRfd3JhcCh+VmFyMikgKyAKICB4bGFiKCJNZWFzdXJlcyIpICsgCiAgeWxhYigiVmFsdWVzIikgKyAKICBnZ3RpdGxlKCJMb2FkaW5ncyBmb3IgUEMxIChNUykiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA2MCwgaGp1c3QgPSAxKSkKYGBgCgpUaGUgUEMgaGFkIGhpZ2ggcG9zaXRpdmUgbG9hZGluZ3MgZm9yIGNoaWxkcmVuIGluIHBvdmVydHksIGNoaWxkcmVuIGluIHNpbmdsZSBwYXJlbnQgaG91c2Vob2xkcywgdW5lbXBsb3ltZW50LCBhZHVsdCBvYmVzaXR5LCBTVElzLCB0ZWVuIGJpcnRocywgYW5kIGluYWRlcXVhdGUgc29jaWFsIHN1cHBvcnRzLiBUaGVyZSB3YXMgYWxzbyBzaWduaWZpY2FudCBuZWdhdGl2ZSBsb2FkaW5nIGluIHRoZSBmb29kIGVudmlyb25tZW50IGluZGV4LCBpbmRpY2F0aW5nIGhpZ2hlciB3ZWlnaHRzIGZvciBjb3VudGllcyB0aGF0IHBlcmZvcm0gcG9vcmx5IGhlcmUuIFBDMSBjYW4gYmUgaW50ZXJwcmV0ZWQgYXMgKip1bnN0YWJsZSBvciBwb29yLXJlc291cmNlIGhvbWUgZW52aXJvbm1lbnRzKiouIEl0IGlzIGltcG9ydGFudCB0byBub3RlIHRoYXQgbG9hZGluZ3Mgd2l0aCBoaWdoZXIgbWVhc3VyZXMgd2VyZSBjYXRlZ29yaXplZCBhcyBIZWFsdGggQmVoYXZpb3JzIGFuZCBTb2NpYWwgYW5kIEVjb25vbWljIEVudmlyb25tZW50IGhhZCB0aGUgaGlnaGVzdCBsb2FkaW5ncyBoZXJlLCBzdWdnZXN0aW5nIHRoYXQgdGhlIHR3byBjYXRlZ29yaWVzIG1heSBub3QgYmUgc28gZGlmZmVyZW50LiAKCiMjI1BDMgpgYGB7cn0KbWVsdGVkICU+JSBmaWx0ZXIoVmFyMj09IlBDMiIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKE1lYXN1cmUsLXZhbHVlKSx5ID0gdmFsdWUsIGZpbGw9RmFjdG9ycykpICsgCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArIAogIGZhY2V0X3dyYXAoflZhcjIpICsgCiAgeGxhYigiTWVhc3VyZXMiKSArIAogIHlsYWIoIlZhbHVlcyIpICsgCiAgZ2d0aXRsZSgiTG9hZGluZ3MgZm9yIFBDMiAoTVMpIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNjAsIGhqdXN0ID0gMSkpCmBgYAoKUEMyIHNlZXMgaGlnaGVyIHBvc2l0aXZlIHdlaWdodHMgZm9yIGRlbnRpc3RzLCBwcmltYXJ5IGNhcmUgcGh5c2ljaWFucywgbWVudGFsIGhlYWx0aCBwcm92aWRlcnMsIGNvbGxlZ2UgZWR1Y2F0aW9uLCBhbmQgdmlvbGVudCBjcmltZS4gVGhlIGdyZWF0ZXN0IG1hZ25pdHVkZSBuZWdhdGl2ZSB3ZWlnaHRzIGluY2x1ZGUgbG9uZyBjb21tdXRlcyBkcml2aW5nIGFsb25lLiBUaGlzIFBDIGNhbiBiZSBpbnRlcnByZXRlZCBhcyAqKmRlbnNpdHkgb2Ygc2VydmljZXMqKiwgd2hlcmUgdGhlcmUgaXMgYSBoaWdoZXIgZGVuc2l0eSBvZiBoZWFsdGggY2FyZSBwcm92aWRlcnMsIG9wcG9ydHVuaXRpZXMgZm9yIGhpZ2hlciBlZHVjYXRpb24sIGFuZCBpbmNpZGVudGFsbHksIHZpb2xlbnQgY3JpbWUuIFRoZSBuZWdhdGl2ZSBsb2FkaW5nIG9uIGxvbmcgY29tbXV0ZSBjb21wbGVtZW50cyB0aGUgaGlnaGVyIGxvYWRpbmdzLCB3aGVyZSBzaG9ydGVyIGRyaXZpbmcvY29tbXV0aW5nIGRpc3RhbmNlcyBhcmUgYXNzb2NpdGVkIHdpdGggdXJiYW4gc2V0dGluZ3MuICAKCiMjI1BDMyAKYGBge3J9Cm1lbHRlZCAlPiUgZmlsdGVyKFZhcjI9PSJQQzMiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihNZWFzdXJlLC12YWx1ZSkseSA9IHZhbHVlLCBmaWxsPUZhY3RvcnMpKSArIAogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKyAKICBmYWNldF93cmFwKH5WYXIyKSArIAogIHhsYWIoIk1lYXN1cmVzIikgKyAKICB5bGFiKCJWYWx1ZXMiKSArIAogIGdndGl0bGUoIkxvYWRpbmdzIGZvciBQQzMgKE1TKSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDYwLCBoanVzdCA9IDEpKQpgYGAKClNldmVyZSBob3VzaW5nIHByb2JsZW1zIGFuZCBiZWluZyB1bmluc3VyZWQgaGF2ZSBoaWdoIHBvc2l0aXZlIGxvYWRpbmdzIGZvciBQQzMsIHdoaWxlIGRyaXZpbmcgYWxvbmUgdG8gd29yayBhbmQgYWxjb2hvbC1pbXBhaXJlZCBkcml2aW5nIGRlYXRocyBoYXZlIGhpZ2ggbmVnYXRpdmUgdmlvbGF0aW9ucy4gQ0hSJ3MgUEh5c2ljYWwgRW52aXJvbm1lbnQgY2F0ZWdvcml6YXRpb24gaXMgbW9yZSByZXByZXNlbnRlZCBoZXJlLCBmb2xsb3dlZCBieSBvbmUgQ2xpbmljYWwgQ2FyZSBtZWFzdXJlICh1bmluc3VyZWQpIGFuZCBvbmUgSGVhbHRoIEJlaGF2aW9yIG1lYXN1cmUgKGFsY29ob2wtaW1wYWlyZWQgZHJpdmluZyBkZWF0aHMpLiBBbHRob3VnaCB0aGlzIGlzIG1vcmUgZGlmZmljdWx0IHRvIGludGVycHJldCwgdGhpcyBQQyBkZXNjcmliZXMgKipiZWluZyB1bmluc3VyZWQgYWdhaW5zdCBhY2NpZGVudHMqKi4gCgojIyNQQzQKYGBge3J9Cm1lbHRlZCAlPiUgZmlsdGVyKFZhcjI9PSJQQzQiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihNZWFzdXJlLC12YWx1ZSkseSA9IHZhbHVlLCBmaWxsPUZhY3RvcnMpKSArIAogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKyAKICBmYWNldF93cmFwKH5WYXIyKSArIAogIHhsYWIoIk1lYXN1cmVzIikgKyAKICB5bGFiKCJWYWx1ZXMiKSArIAogIGdndGl0bGUoIkxvYWRpbmdzIGZvciBQQzQgKE1TKSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDYwLCBoanVzdCA9IDEpKQpgYGAKCkZpbmFsbHksIFBDNCBzZWVzIGhpZ2ggbG9hZGluZyBvbiBhaXIgcG9sbHV0aW9uIGFuZCBhY2Nlc3MgdG8gZXhlcmNpc2Ugb3Bwb3J0dW5pdGllcywgYWdhaW4gYWxsdWRpbmcgdG8gdGhlIHVyYmFuIGNvbnRleHQgYnV0IHNwZWNpZmljYWxseSByZWZlcnJpbmcgdG8gdGhlICoqaW5hYmlsaXR5IHRvIGFjY2VzcyB0aGUgb3V0ZG9vcnMqKi4KCiMjIyNXZWlnaHRzClRoZXNlIGZvdXIgUENzIGNhbiBiZSBhc3NpZ25lZCB3ZWlnaHRzIGNhbGN1bGF0ZWQgYnkgdGhlIHBlcmNlbnQgb2YgdmFyaWFuY2UgZWFjaCBQQyBhY2NvdW50cyBmb3IgZGl2aWRlZCBieSB0aGUgdG90YWwgYW1vdW50IG8gdmFyaWFuY2UgdGhlIGNob3NlbiBQQ3MgYWNjb3VudCBmb3IuCgokJApGYWN0b3JfMSA9IFxmcmFjezAuMjcyNX17MC41NDc0OH0sIEZhY3Rvcl8yID0gXGZyYWN7MC4xNTk4fXswLjU0NzQ4fSwgRmFjdG9yXzMgPSBcZnJhY3swLjA2MTk5fXswLjU0NzQ4fSAsRmFjdG9yXzQ9XGZyYWN7MC4wNTMyNX17MC41NDc0OH0KJCQKClRoZSBmb3VyIFBDcyBhcmUgdGhlIGZvbGxvd2luZzogCiogKio0OS44JSBSZXNvdXJjZS1wb29yIEhvbWUgRW52aXJvbm1lbnRzKioKKiAqKjI5LjIlIERlbnNpdHkgb2YgU2VydmljZXMqKgoqICoqMTEuMyUgVW5pbnN1cmVkKioKKiAqKjkuNyUgTm8gT3V0ZG9vciBBY2Nlc3MqKgoKSW50ZXJlc3RpbmdseSBmb3IgTWlzc2lzc2lwcGksIGNvdW50eSBzY29yZXMgb24gd2hhdCBDSFIgY29uc2lkZXJzIGhlYWx0aCBtZWFzdXJlcyBhY3R1YWxseSBmYWxsIGludG8gY2F0ZWdvcmllcyBvZiBob21lIGVudmlyb25lbW50cywgYWNjZXNzIHRvIHByb3ZpZGVycywgaW5zdXJhbmNlLCBhbmQgb3V0ZG9vciBhY3Rpdml0aWVzLiBPdXIgUHJpbmNpcGFsIENvbXBvbmVudCBBbmFsYXlzaXMgdGhhdCBiZWluZyAnaGVhbHRoeScgaGFzIGEgbG90IGxlc3MgdG8gZG8gd2l0aCB3aGV0aGVyIGNvdW50aWVzIHBhcnRpY2lwYXRlIGluIGhlYWx0aHkgYmVoYXZpb3JzLCBidXQgd2hldGhlciB0aGVyZSBhcmUgb3Bwb3J0dW5pdGllcyBmb3IgaW5kaXZpZHVhbHMgdG8gZ3JvdyB1cCBpbiBoZWFsdGh5IGVudmlyb25tZW50cyBhbmQgc2VlayBhZmZvcmRhYmxlIGhlYWx0aGNhcmUgd2hlbiB0aGV5IG5lZWQgaXQuIAoKIyNXZXN0IFZpcmdpbmlhCgpOb3cgd2UnbGwgdGFrZSBhIGxvb2sgYXQgdGhlIHNhbWUgcHJvY2VzcyBmb3IgV2VzdCBWaXJnaW5pYS4KYGBge3J9CnZhcldWIDwtIHZhcldWICU+JSBtdXRhdGVfYWxsKGZ1bnMoaWZlbHNlKGlzLm5hKC4pLCAwLCAuKSkpCgpXVi5wY2EgPC0gcHJjb21wKHZhcldWLAogICAgICAgICAgICAgICAgIGNlbnRlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgc2NhbGUuID0gVFJVRSkgCnN1bW1hcnkoV1YucGNhKQoKYGBgCgpgYGB7cn0Kc2NyZWVwbG90KFdWLnBjYSwgbnBjcyA9IDI5LCB0eXBlID0gImxpbmVzIikKYGBgCgpCYXNlZCBvbiB0aGUgc2NyZWUgcGxvdCwgd2UgY2FuIGNob29zZSBmb3VyIHByaW5jaXBhbCBjb21wb25lbnRzIGFnYWluLiAKCmBgYHtyfQpsb2FkaW5ncyA8LSBhcy5kYXRhLmZyYW1lKFdWLnBjYSRyb3RhdGlvbikgI2NyZWF0ZSBhIGRhdGEgZnJhbWUgb2YgUENBIGxvYWRpbmdzCgptZWx0ZWQgPC0gIG1lbHQoV1YucGNhJHJvdGF0aW9uWywxOjRdKQoKbWVsdGVkIDwtIGZ1bGxfam9pbihtZWx0ZWQsIGZhY3Rvcm5hbWVzLCBieSA9IGMoIlZhcjEiPSAiTWVhc3VyZV9BYmIiKSkgI2pvaW4gdGhlIENIUiBjYXRlZ29yaWVzCmBgYAoKIyMjUEMxCmBgYHtyfQptZWx0ZWQgJT4lIGZpbHRlcihWYXIyPT0iUEMxIikgJT4lIAogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoTWVhc3VyZSwtdmFsdWUpLHkgPSB2YWx1ZSwgZmlsbD1GYWN0b3JzKSkgKyAKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsgCiAgZmFjZXRfd3JhcCh+VmFyMikgKyAKICB4bGFiKCJNZWFzdXJlcyIpICsgCiAgeWxhYigiVmFsdWVzIikgKyAKICBnZ3RpdGxlKCJMb2FkaW5ncyBmb3IgUEMxIChXVikiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA2MCwgaGp1c3QgPSAxKSkKYGBgCgpUaGlzIHRpbWUsIHdlIGhhdmUgaGlnaCBwb3NpdGl2ZSBsb2FkaW5nIG9uIHNvbWUgY29sbGVnZSBlZHVjYXRpb24sIGF2YWlsYWJpbGl0eSBvZiBoZWFsdGggY2FyZSBwcm92aWRlcnMgKGRlbnRpc3RyeSwgbWVudGFsIGhlYWx0aCwgYW5kIHByaW1hcnkgY2FyZSksIGFuZCBTVElzIGFuZCBhY2Nlc3MgdG8gZXhlcmNpc2Ugb3Bwb3J0dW5pdGllcy4gVGhlcmUgaXMgaGlnaCBuZWdhdGl2ZSBsb2FkaW5nIG9uIHBoeXNpY2FsIGluYWN0aXZpdHksIGFkdWx0IG9iZXNpdHksIGluanVyeSBkZWF0aHMsIGFuZCBjaGlsZHJlbiBpbiBwb3ZlcnR5LiBQQzEgc3VtbWFyaXplcyB0aGUgZG9tYWluIG9mIGhhdmluZyBhY2Nlc3MgdG8gaGVhbHRoIGNhcmUgcHJvdmlkZXJzIGFuZCBrbm93aW5nIGhvdyB0byBzZWVrIGNhcmUsIGFzIHdlbGwgYXMgYmVpbmcgbW9yZSBwaHlzaWNhbGx5IGFjdGl2ZSBhbmQgZmluYW5jaWFsbHkgc2VjdXJlLiBUaGlzIFBDMSBjYW4gYmUgc3VtbWFyaXplZCBhcyAqKmhlYWx0aCBlbmdhZ2VtZW50KiouCgojIyNQQzIKYGBge3J9Cm1lbHRlZCAlPiUgZmlsdGVyKFZhcjI9PSJQQzIiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihNZWFzdXJlLC12YWx1ZSkseSA9IHZhbHVlLCBmaWxsPUZhY3RvcnMpKSArIAogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKyAKICBmYWNldF93cmFwKH5WYXIyKSArIAogIHhsYWIoIk1lYXN1cmVzIikgKyAKICB5bGFiKCJWYWx1ZXMiKSArIAogIGdndGl0bGUoIkxvYWRpbmdzIGZvciBQQzIgKFdWKSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDYwLCBoanVzdCA9IDEpKQpgYGAKCkluIFBDMiwgbW9yZSBtZWFzdXJlcyBoYXZlIGhpZ2ggcG9zaXRpdmUgbG9hZGluZyB0aGFuIGhpZ2ggbmVnYXRpdmUgbG9hZGluZ3MuIFRoZSBwb3NpdGl2ZSBsb2FkaW5ncyBpbmNsdWRlIHRlZW4gYmlydGhzLCBoZWFsdGggY2FyZSBwcm92aWRlcnMsIHZpb2xlbnQgY3JpbWUsIGRyaXZpbmcgYWxvbmUgdG8gd29yaywgU1RJcywgaW5hZGVxdWF0ZSBzb2NpYWwgc3VwcG9ydCwgYW5kIGluanVyeSBkZWF0aHMuIE5lZ2F0aXZlIGxvYWRpbmdzIGluY2x1ZGUgaGlnaCBzY2hvb2wgZ3JhZHVhdGlvbiwgbG9uZyBjb21tdXRlL2RyaXZpbmcgYWxvbmUsIGFuZCBleGNlc3NpdmUgZHJpbmtpbmcuIFRoaXMgY29tcG9uZW50IGFwcGVhcnMgbGVzcyBoZWFsdGggcmVsYXRlZCwgYnV0IHJhdGhlciBkZXNjcmliZXMgeW91bmcgYW5kIHBvb3IgZmFtaWxpZXMgaW4gc21hbGwgdG93bnMuIFRoaXMgaXMgc2ltaWxhciB0byB0aGUgKip1bnN0YWJsZSBob21lIGVudmlyb25tZW50KiogUEMgZm9yIE1pc3Npc3NpcHBpLiAKCgojIyNQQzMgCmBgYHtyfQptZWx0ZWQgJT4lIGZpbHRlcihWYXIyPT0iUEMzIikgJT4lIAogIGdncGxvdChhZXMoeCA9IHJlb3JkZXIoTWVhc3VyZSwtdmFsdWUpLHkgPSB2YWx1ZSwgZmlsbD1GYWN0b3JzKSkgKyAKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsgCiAgZmFjZXRfd3JhcCh+VmFyMikgKyAKICB4bGFiKCJNZWFzdXJlcyIpICsgCiAgeWxhYigiVmFsdWVzIikgKyAKICBnZ3RpdGxlKCJMb2FkaW5ncyBmb3IgUEMzIChXVikiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA2MCwgaGp1c3QgPSAxKSkKYGBgCgpGb3IgUEMzLCB0aGVyZSBhcmUgbW9yZSBuZWdhdGl2ZSBsb2FkaW5ncyB0aGFuIHBvc2l0aXZlLiBOZWdhdGl2ZSBsb2FkaW5nIGluY2x1ZGVzIGV4Y2Vzc2l2ZSBkcmlua2luZywgc2V2ZXJlIGhvdXNpbmcgcHJvYmxlbXMsIGRyaW5raW5nIHdhdGVyIHZpb2xhdGlvbnMsIGNoaWxkcmVuIGluIHBvb3IgaG91c2Vob2xkcywgYW5kIGJlaW5nIHVuaW5zdXJlZC4gVGhlcmUgaXMgaGlnaCBwb3NpdGl2ZSBsb2FkaW5nIGZvciBmb29kIGVudmlyb25tZW50LCBmb2xsb3dlZCBieSBkcml2aW5nIGFsb25lIHRvIHdvcmsuIFRoaXMgUEMgZGVzY3JpYmVzIHVuaGVhbHRoeSBjb25zdW1wdGlvbiBwYXR0ZXJucyBhbmQgbGl2aW5nIGluIHVuc2FmZSBlbnZpcm9ubWVudHMsIGFuZCBjYW4gYmUgY2FsbGVkICoqdG94aWMgY29uc3VtcHRpb24qKi4KCiMjI1BDNApgYGB7cn0KbWVsdGVkICU+JSBmaWx0ZXIoVmFyMj09IlBDNCIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKE1lYXN1cmUsLXZhbHVlKSx5ID0gdmFsdWUsIGZpbGw9RmFjdG9ycykpICsgCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArIAogIGZhY2V0X3dyYXAoflZhcjIpICsgCiAgeGxhYigiTWVhc3VyZXMiKSArIAogIHlsYWIoIlZhbHVlcyIpICsgCiAgZ2d0aXRsZSgiTG9hZGluZ3MgZm9yIFBDNCAoV1YpIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNjAsIGhqdXN0ID0gMSkpCmBgYAoKRmluYWxseSwgUEM0IGRlc2NyaWJlcyBhaXIgcG9sbHV0aW9uIChzaW1pbGFyIHRvIHRvIE1pc3Npc2lwcGkpLCBhcyB3ZWxsIGFzIGxvdyBkaWFiZXRpYyBzY3JlZW5pbmcgYW5kIHVuaW5zdXJhbmNlIHJhdGVzLiBUaGlzIFBDIGlzIHB1enpsaW5nIHRvIGludGVycHJldCwgdGhvdWdoIGl0IHNob3VsZCBiZSBub3RlZCB0aGF0IGRpYWJldGljIHNjcmVlbmluZyByZWZlcnMgdG8gdGhlIHBlcmNlbnRhZ2Ugb2YgTWVkaWNhcmUgZW5yb2xsZWVzIChhZ2UgNjUrKSB3aG8gcmVjZWl2ZSBIYkExYyBzY3JlZW5pbmcsIHdoaWxlIHRoZSB1bmluc3VyYW5jZSByYXRlIHJlZmVycyB0byB0aGUgcGVyY2VudCBvZiB0aGUgcG9wdWxhdGlvbiB1bmRlciBhZ2UgNjUgd2hvIGRvIG5vdCBoYXZlIGhlYWx0aCBpbnN1cmFuY2UuIFRoZXJlZm9yZSwgdGhpcyBQQyBtaWdodCBkZXNjcmliZSBjb3VudGllcyB3aXRoIHlvdW5nZXIsIGluc3VyZWQgcG9wdWxhdGlvbnMgd2hlcmUgcG9sbHV0aW9uLCBhbmQgcGVyaGFwcyBpbmR1c3RyeSAoY29hbCksIGlzIHByZXNlbnQuIFRoaXMgcmVsYXRpb25zaGlwIHdhcyBleHBsb3JlZCBmdXJ0aGVyIHdpdGggbWFwcywgd2hlcmUgYXJlYXMgb2YgbG93IHVuaW5zdXJhbmNlIGFyYXRlcyBhbmQgaGlnaCBwb2xsdXRpb24gYXJlIG5vcnRoZXJuIGNvdW50aWVzIGJvcmRlcmluZyBQZW5uc3lsdmFuaWEuIFRoaXMgUEMgY291bGQgYmUgY2FsbGVkICoqb2NjdXBhdGlvbmFsIGhlYWx0aCoqLgoKYGBge3J9CldWX3VuaW5zdXJlIDwtIHpNU19XViAlPiUgc2VsZWN0KEZJUFMsIFVuaW5zdXJlX3BlcmNlbnQpCmNvbG5hbWVzKFdWX3VuaW5zdXJlKSA8LSBjKCJyZWdpb24iLCAidmFsdWUiKQoKY291bnR5X2Nob3JvcGxldGgoV1ZfdW5pbnN1cmUsIAogICAgICAgICAgICAgICAgICAgdGl0bGUgICAgICAgICA9ICJVbmluc3VyZWQgWi1TY29yZXMgaW4gV2VzdCBWaXJnaW5pYSIsIAogICAgICAgICAgICAgICAgICAgbGVnZW5kICAgICAgICA9ICJVbmluc3VyZWQgIFotU2NvcmVzIiwKICAgICAgICAgICAgICAgICAgIHN0YXRlX3pvb20gICAgPSAid2VzdCB2aXJnaW5pYSIsCiAgICAgICAgICAgICAgICAgICByZWZlcmVuY2VfbWFwID0gVFJVRSkKYGBgCgoKYGBge3J9CldWX2FpciA8LSB6TVNfV1YgJT4lIHNlbGVjdChGSVBTLCBhaXJwb2xsdXRpb24pCmNvbG5hbWVzKFdWX2FpcikgPC0gYygicmVnaW9uIiwgInZhbHVlIikKCmNvdW50eV9jaG9yb3BsZXRoKFdWX2FpciwgCiAgICAgICAgICAgICAgICAgICB0aXRsZSAgICAgICAgID0gIkFpciBQb2xsdXRpb24gWi1TY29yZXMgaW4gV2VzdCBWaXJnaW5pYSIsIAogICAgICAgICAgICAgICAgICAgbGVnZW5kICAgICAgICA9ICJBaXIgUG9sbHV0aW9uIFotU2NvcmVzIiwKICAgICAgICAgICAgICAgICAgIHN0YXRlX3pvb20gICAgPSAid2VzdCB2aXJnaW5pYSIsCiAgICAgICAgICAgICAgICAgICByZWZlcmVuY2VfbWFwID0gVFJVRSkKYGBgCgoKCiQkCkZhY3Rvcl8xID0gXGZyYWN7MC4yNzU4fXswLjU1OTM2fSwgRmFjdG9yXzIgPSBcZnJhY3swLjEyNzd9ezAuNTU5MzZ9LCBGYWN0b3JfMyA9IFxmcmFjezAuMDg3MTV9ezAuNTU5MzZ9ICxGYWN0b3JfND1cZnJhY3swLjA2ODY2fXswLjU1OTM2fQokJAoKVGhlIGZvdXIgUENzIGZvciBXZXN0IFZpcmdpbmlhIGFyZSB0aGUgZm9sbG93aW5nOiAKKiAqKjQ5LjMlIEhlYWx0aCBFbmdhZ2VtZW50KioKKiAqKjIyLjglIFVuc3RhYmxlIEhvbWUgRW52aXJvbm1lbnQqKgoqICoqMTUuNiUgVG94aWMgQ29uc3VtcHRpb24qKgoqICoqMTIuMiUgT2NjdXBhdGlvbmFsIEhlYWx0aCoqCgojQ0hSIHZzLiBQQ0EKCiMjIkhpc3RvcmljYWxseSBJbmZvcm1lZCIgV2VpZ2h0cyB2cy4gRW1waXJpY2FsIFdlaWdodHMKCk9uIHRoZSBDb3VudHkgSGVhbHRoIFJhbmtpbmcgW3dlYnNpdGVdKGh0dHA6Ly93d3cuY291bnR5aGVhbHRocmFua2luZ3Mub3JnL3JhbmtpbmctbWV0aG9kcy9yYW5raW5nLXN5c3RlbSksIHRoZXkgZGlzY3VzcyBvcmdhbml6aW5nIDI5IG1lYXN1cmVzIG9mIGhlYWx0aCBpbnRvIGZvdXIgY29tcG9uZW50cyBhbmQgY2hvb3Npbmcgd2VpZ2h0cyBiYXNlZCBvbiAic2NpZW50aWZpYyByZXNlYXJjaCwgYXZhaWxhYmxlIGRhdGEsIGV4cGVydCBvcGluaW9uLCBzdGF0aXN0aWNhbCBhbmFseXNpcy4iIEluIG91ciBQcmluY2lwYWwgQ29tcG9uZW50IEFuYWx5c2lzLCB3ZSB1c2VkIGEgcHVyZWx5IGVtcGlyaWNhbCBhcHByb2FjaCB0byBhbmFseXplIHRoZSB2YXJpYW5jZSBhY3Jvc3MgY291bnRpZXMgaW4gdGhlIHR3byBzdGF0ZXMgdGhhdCBzYXcgdGhlIGdyZWF0ZXN0IGRlY2xpbmUgaW4gbGlmZSBleHBlY3RhbmN5LiBXZSB3YW50ZWQgdG8gc2VlIHdoYXQgbWF0dGVycyBtb3N0IHRvICdoZWFsdGgnIGluIHRoZXNlIHN0YXRlcycgY291bnRpZXMsIGFuZCBpZiB0aGUgd2VpZ2h0cyBmb3IgdGhlIGRpZmZlcmVudCBjYXRlZ29yaWVzIHdvdWxkIGJlIGRpZmZlcmVudCBmcm9tIENIUi4gSG93ZXZlciwgb25jZSB3ZSBhY3R1YWxseSBwZXJmb3JtZWQgdGhlIGFuYWx5c2lzIG9uIHRoZSAyOSBtZWFzdXJlcywgd2UgcmVhbGl6ZWQgdGhhdCB0aGUgY29tcG9uZW50cyB3ZXJlIGRlc2NyaWJpbmcgaXNzdWVzIG9mIHdlbGZhcmUsIHRoZSBidWlsdCBhbmQgcGh5c2ljYWwgZW52aXJvbm1lbnQsIGFuZCBhY2Nlc3MgdG8gYW5kIGVuZ2FnZW1lbnQgd2l0aCBoZWFsdGggc2VydmljZXMuIEEgdGFibGUgY29tcGFyaW5nIHRoZSBjb21wb25lbnRzIGFuZCB3ZWlnaHRzIGZyb20gQ0hSIGFuZCBvdXIgUENBIGFuYWx5c2VzIGlzIHNob3duIGJlbG93OgoKCkNIUiB8IE1TIFBDQSB8IFdWIFBDQQotLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0KNDAlIFNvY2lhbCBhbmQgRWNvbm9taWMgRW52aXJvbm1lbnQgfCA0OS44JSBSZXNvdXJjZS1wb29yIEhvbWUgRW52aXJvbm1lbnRzIHwgNDkuMyUgSGVhbHRoIEVuZ2FnZW1lbnQKMzAlIEhlYWx0aCBCZWhhdmlvcnMgfCAyOS4yJSBEZW5zaXR5IG9mIFNlcnZpY2VzIHwgMjIuOCUgVW5zdGFibGUgSG9tZSBFbnZpcm9ubWVudAoyMCUgQ2xpbmljYWwgQ2FyZSB8IDExLjMlIFVuaW5zdXJlZCB8IDE1LjYlIFRveGljIENvbnN1bXB0aW9uCjEwJSBQaHlzaWNhbCBFbnZpcm9ubWVudCB8IDkuNyUgTm8gT3V0ZG9vciBBY2Nlc3MgfCAxMi4yJSBPY2N1cGF0aW9uYWwgSGVhbHRoCgpGb3IgQ0hSLCBhIGNvdW50eSdzIGhlYWx0aCBpcyBkZXRlcm1pbmVkIGxhcmdlbHkgYnkgc29jaWFsIGFuZCBlY29ub21pYyBlbnZpcm9ubWVudHMgYW5kIGhlYWx0aCBiZWhhdmlvcnMsIHdoaWNoIGFjY291bnRzIGZvciA3MCUgb2YgdGhlaXIgb3ZlcmFsbCBoZWFsdGggbWVhc3VyZS4gRm9yIG91ciBQQ0EgYW5hbHlzZXMsIHRoZXNlIHNvY2lhbCBhbmQgZWNvbm9taWMgZGV0ZXJtaW5hbnRzIGFwcGVhcmVkIGluIG1hbnkgb2YgdGhlIHByaW5jaXBhbCBjb21wb25lbnRzIGZvciBib3RoIHN0YXRlcywgYWxvbmcgd2l0aCBvdGhlciBtZWFzdXJlcyB0aGF0IHdlcmUgY29uc2lkZXJlZCBzZXBhcmF0ZSBmcm9tIFNvY2lhbCBhbmQgRWNvbm9taWMgRmFjdG9ycyBieSBDSFItLSBzdWNoIGFzIGRlbnNpdHkgb2YgcHJvdmlkZXJzLCB1bnNhZmUgZHJpbmtpbmcgd2F0ZXIsIHRlZW4gYmlydGhzLCBhbmQgYWlyIHBvbGx1dGlvbi4gT3VyIFBDcyBmb3IgTWlzc2lzc2lwcGkgYW5kIFdlc3QgVmlyZ2luaWEgaGlnaGxpZ2h0IHRoZSBzb2NpYWwgY29udGV4dCBvZiB0aGVzZSBlbnZpcm9ubWVudGFsIGZhY3RvcnMsIGFuZCBob3cgdGhleSBhcmUgc28gaW50ZXJjb25uZWN0ZWQuIAoKRm9yIGV4YW1wbGUsIG91ciBjb21wb25lbnRzIGRldGVybWluZWQgZm9yIFBDQSBpbiBNaXNzaXNzaXBwaSBkZXNjcmliZWQgdGhlIGltcG9ydGFuY2Ugb2YgaG9tZSBhbmQgcGh5c2ljYWwgZW52aXJvbm1lbnRzLCBhcyB3ZWxsIGFzIHByb3hpbWl0eSB0byBoZWFsdGggc2VydmljZXMgYW5kIGJlaW5nIGluc3VyZWQgYWdhaW5zdCBhY2NpZGVudHMuIEluIFdlc3QgVmlyZ2luaWEsIHRoZSBjb21wb25lbnRzIGRlc2NyaWJlIGVuZ2FnZW1lbnQgd2l0aCBoZWFsdGh5IGFjdGl2aXRpZXMsIGFzIHdlbGwgYXMgYWdhaW4sIHBvb3IgaG9tZSBlbnZpcm9ubWVudHMgb3IgdG94aWMgcGh5c2ljYWwgZW52aXJvbm1lbnRzLiBUaGVzZSBjb21wb25lbnRzIGVtcGhhc2l6ZSB0aGUgaW1wb3J0YW5jZSBvZiB3aGVyZSBwZW9wbGUgbGl2ZSwgd2hlcmUgbG9jYXRpb24gZGV0ZXJtaW5lcyB0aGUgY29uZGl0aW9ucyB0aGF0IGFmZmVjdCB0aGVpciBoZWFsdGggKHBvbGx1dGlvbiwgdW5zYWZlIGhvdXNpbmcsIGV4ZXJjaXNlIG9wcG9ydHVuaXRpZXMpLCBhbmQgaG93IGxpa2VseSBpdCBpcyB0aGF0IHRoZXkgYXJlIGFibGUgdG8gYWNjZXNzIGhlYWx0aCBzZXJ2aWNlcyB3aGVuIGNhcmUgaXMgbmVlZGVkIChkaXN0YW5jZSB0byBwcm92aWRlcnMgYW5kIGluc3VyYW5jZSkuIAoKSW1wbGljYXRpb25zIGZvciBvdXIgcHJpbmNpcGFsIGNvbXBvbmVudCBhbmFseXNlcyBpbmNsdWRlIGZvY3VzaW5nIG9uIHRoZSBidWlsdCBhbmQgcGh5c2ljYWwgZW52aXJvbm1lbnRzIG9mIGNvbW11bml0aWVzIEltcHJvdmluZyBob3VzaW5nLCBlbnZpcm9ubWVudGFsIGNvbmRpdGlvbnMsIGFuZCBlbnN1cmluZyBhY2Nlc3MgKGdlb2dyYXBoaWNhbGx5IGFuZCBmaW5hbmNpYWxseSkgdG8gaGVhbHRoIHNlcnZpY2VzLCBhcmUgbGlrZWx5IHRvIGltcGFjdCBjb21tdW5pdGVzIG1vcmUgdGhhbiBhZGRyZXNzaW5nIHNwZWNpZmljIGhlYWx0aCBmYWN0b3JzIGxpa2UgU1RJcyBvciBtb25pdG9yaW5nIGRpYWJldGVzLiBUaGlzIGNvbnRyYXN0cyBmcm9tIHRoZSBpbXBsaWNhdGlvbnMgb2YgQ0hSJ3Mgd2VpZ2h0cywgd2hlcmUgcGh5c2ljYWwgZW52aXJvbm1lbnQgYW5kIGNsaW5pY2FsIGNhcmUgYXJlIHRob3VnaHQgdG8gYmUgZGlmZmVyZW50IGZyb20gc29jaWFsL2Vjb25vbWljIGZhY3RvcnMgYW5kIGhlYWx0aCBiZWhhdmlvcnMuIAoKI1doYXQgbmV4dD8gCgpXaXRoIG91ciBQQ0EgYW5hbHlzZXMsIHdlIHdlcmUgYWJsZSB0byBkZXNjcmliZSBuZXcgcGF0dGVybnMgb2YgaGVhbHRoIGRldGVybWluYW50cyBhbmQgYmVoYXZpb3JzIHRoYXQgZGlmZmVyZWQgZnJvbSBob3cgQ0hSIHBlcmNlaXZlcyBoZWFsdGguIENIUiBzdGF0ZXMgdGhhdCB0aGVpciBtaXNzaW9uIGluIGNyZWF0aW5nIHRoZXNlIHJhbmtpbmdzIGlzIHRvIHByb3ZpZGUgc3RhdGVzIHdpdGggaW5mb3JtYXRpb24gYWJvdXQgd2hlcmUgYW5kIGhvdyB0byBmb2N1cyB0aGVpciBlbmVyZ2llcyBpbiBpbXByb3ZpbmcgcG9wdWxhdGlvbiBoZWFsdGguIFdlIGhvcGUgdGhhdCBhIGRpZmZlcmVudCBhcHByb2FjaCB0byB0aGVzZSByYW5raW5ncyB1c2luZyBQQ0EgcG9pbnQgdG8gb3RoZXIgcGF0dGVybnMgaW4gcG9wdWxhdGlvbiBoZWFsdGgsIGFuZCBlbmNvdXJhZ2UgYSBtb3JlIGhvbGlzdGljLCBzb2NpYWwgd2VsZmFyZSBhcHByb2FjaCB0byBpbXByb3ZpbmcgaGVhbHRoLiBQQ0EgdGVsbHMgdXMgdGhhdCB3aGF0IGFyZSB0cmFkaXRpb25hbGx5ICdoZWFsdGggbWVhc3VyZXMnIGFjdHVhbGx5IGRlc2NyaWJlIHNvY2lhbCB3ZWxsIGJlaW5nIGFzIHdlbGwsIHdoaWNoIHNob3VsZCBiZSBhIGZvY3VzIGluIHB1YmxpYyBoZWFsdGggZWZmb3J0cy4gCgoKCgo=